package com.evildog.workspace.system.application.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.evildog.workspace.common.object.PageQuery;
import com.evildog.workspace.common.result.PagedResult;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evildog.workspace.dependencies.mybatis.base.TableLinkService;
import com.evildog.workspace.dependencies.mybatis.enums.BaseStatusEnum;
import com.evildog.workspace.dependencies.mybatis.object.BaseStatusDTO;
import com.evildog.workspace.dependencies.mybatis.object.LinkIdDTO;
import com.evildog.workspace.dependencies.mybatis.object.QueryConditionDTO;
import com.evildog.workspace.dependencies.mybatis.util.BaseStatusValidate;
import com.evildog.workspace.dependencies.mybatis.util.QueryConditionUtils;
import com.evildog.workspace.system.application.bo.UserGroupBO;
import com.evildog.workspace.system.application.bo.UserGroupListBO;
import com.evildog.workspace.system.application.bo.UserGroupPageBO;
import com.evildog.workspace.system.application.convert.UserGroupConvert;
import com.evildog.workspace.system.application.dto.UserGroupDTO;
import com.evildog.workspace.system.application.dto.UserGroupListDTO;
import com.evildog.workspace.system.application.dto.UserGroupPageDTO;
import com.evildog.workspace.system.application.entity.*;
import com.evildog.workspace.system.application.mapper.UserGroupMapper;
import com.evildog.workspace.system.application.mapper.UserUserGroupLinkMapper;
import com.evildog.workspace.system.application.service.RoleUserGroupLinkService;
import com.evildog.workspace.system.application.service.UserGroupService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;

@Service
@AllArgsConstructor
public class UserGroupServiceImpl extends ServiceImpl<UserGroupMapper, UserGroup> implements UserGroupService {

    private final UserUserGroupLinkMapper userUserGroupLinkMapper;
    private final RoleUserGroupLinkService roleUserGroupLinkService;
    private final TableLinkService tableLinkService;

    @Override
    public PagedResult<UserGroupPageBO> getPageList(PageQuery query, List<QueryConditionDTO> queryConditions, UserGroupPageDTO pageDTO) {
        IPage<UserGroupPageDO> page = this.baseMapper.getPageList(
                QueryConditionUtils.getPagination(query),
                queryConditions,
                pageDTO);
        return UserGroupConvert.INSTANCE.convert(page);
    }

    @Override
    public List<UserGroupListBO> getList(List<QueryConditionDTO> queryCondition, UserGroupListDTO dto) {
        List<UserGroupListDO> userGroupList = this.baseMapper.getList(queryCondition, dto);
        return UserGroupConvert.INSTANCE.convert(userGroupList);
    }

    @Override
    public UserGroupBO getDetailById(Long id) {
        UserGroup userGroup = this.getById(id);
        Assert.notNull(userGroup, "userGroup is null!");
        return UserGroupConvert.INSTANCE.convert(userGroup);
    }

    @Override
    public boolean save(UserGroupDTO dto){
        UserGroup newUserGroup = UserGroupConvert.INSTANCE.convert(dto);
        return save(newUserGroup);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean remove(Long id) {
        if(removeById(id)){

            // 删除与用户的关联
            tableLinkService.removeByLinkId(userUserGroupLinkMapper, UserUserGroupLink::getUserGroupId, id);

            // 删除与角色关联
            tableLinkService.removeByLinkId(roleUserGroupLinkService, RoleUserGroupLink::getUserGroupId, id);

            return true;

        }
        return false;
    }

    @Override
    public boolean updateRoles(Long id, LinkIdDTO param) {
        UserGroup userGroup = getById(id);
        Assert.notNull(userGroup, "userGroup is null!");

        tableLinkService.removeByLinkId(roleUserGroupLinkService, RoleUserGroupLink::getUserGroupId, id);

        List<Long> roleIds = param.getLinkIds();

        List<RoleUserGroupLink> links = new ArrayList<>();
        roleIds.forEach(roleId ->
                links.add(new RoleUserGroupLink()
                        .setUserGroupId(id)
                        .setRoleId(roleId)
                )
        );

        return roleUserGroupLinkService.saveBatch(links);
    }

    @Override
    public boolean updateStatus(Long id, BaseStatusDTO dto) {
        UserGroup userGroup = getById(id);
        Assert.notNull(userGroup, "userGroup is null!");

        Integer status = dto.getStatus();
        BaseStatusValidate.checkStatusValid(status);

        UserGroup newUserGroup = new UserGroup()
                .setId(id)
                .setStatus(status);
        return updateById(newUserGroup);
    }

    @Override
    public List<UserGroupListBO> getList(Long userId) {
        List<Long> userGroupIds = tableLinkService.getLinkIdList(userUserGroupLinkMapper, UserUserGroupLink::getUserGroupId, UserUserGroupLink::getUserId, userId);

        if(userGroupIds.isEmpty()){
            return new ArrayList<>();
        }


        List<UserGroup> userGroups = list(Wrappers.<UserGroup>lambdaQuery()
                .eq(UserGroup::getStatus, BaseStatusEnum.IS_ABLE.getStatus())
                .in(UserGroup::getId, userGroupIds)
        );

        return UserGroupConvert.INSTANCE.convertBOList(userGroups);
    }

    @Override
    public boolean updateById(Long id, UserGroupDTO dto){
        UserGroup oldUserGroup = getById(id);
        Assert.notNull(oldUserGroup, "userGroup is null!");
        UserGroup newUserGroup = UserGroupConvert.INSTANCE.convert(dto);
        newUserGroup.setId(id);
        return updateById(newUserGroup);
    }
}
